#import "EspBlufiPlugin.h"
#import "BlufiClient.h"
#import "ESPPeripheral.h"
#import "ESPFBYBLEHelper.h"
#import "ESPDataConversion.h"
#import <CoreLocation/CoreLocation.h>
#import <SystemConfiguration/CaptiveNetwork.h>

// 定义模式常量（如果 iOS SDK 的枚举值不同）
static const NSInteger OP_MODE_STA = 1;
static const NSInteger OP_MODE_AP = 2;

@interface EspBlufiPlugin () <CBCentralManagerDelegate, CBPeripheralDelegate, BlufiDelegate>
@property(nonatomic, strong) ESPFBYBLEHelper *espFBYBleHelper;
@property(nonatomic, copy) NSMutableDictionary *peripheralDictionary;
@property(nonatomic, strong) NSString *filterContent;
@property(strong, nonatomic) ESPPeripheral *device;
@property(strong, nonatomic) BlufiClient *blufiClient;
@property(assign, atomic) BOOL connected;
@property(nonatomic, retain) EspBlufiPluginStreamHandler *stateStreamHandler;
@end

@implementation EspBlufiPlugin

+ (void)registerWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar {
    FlutterMethodChannel *channel = [FlutterMethodChannel
            methodChannelWithName:@"esp_blufi"
                  binaryMessenger:[registrar messenger]];
    EspBlufiPlugin *instance = [[EspBlufiPlugin alloc] init];
    FlutterEventChannel *stateChannel = [FlutterEventChannel eventChannelWithName:@"esp_blufi/state" binaryMessenger:[registrar messenger]];
    EspBlufiPluginStreamHandler *stateStreamHandler = [[EspBlufiPluginStreamHandler alloc] init];
    [stateChannel setStreamHandler:stateStreamHandler];
    instance.stateStreamHandler = stateStreamHandler;

    [registrar addMethodCallDelegate:instance channel:channel];
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.espFBYBleHelper = [ESPFBYBLEHelper share];
        self.filterContent = [ESPDataConversion loadBlufiScanFilter];
    }
    return self;
}

// 设置设备模式（只设置模式，不配置其他参数）
- (void)setDeviceMode:(NSInteger)mode {
    // 检查 BlufiClient 是否已初始化并且已连接
    if (_blufiClient && _connected) {
        // 创建 BlufiConfigureParams 实例
        BlufiConfigureParams *params = [[BlufiConfigureParams alloc] init];

        // 设置操作模式
        params.opMode = (OpMode)mode;

        // 不设置其他参数，只设置模式
        [_blufiClient configure:params];

        NSLog(@"iOS setDeviceMode called with mode: %ld", (long)mode);
        [self updateMessage:[self makeJsonWithCommand:@"set_device_mode" data:[NSString stringWithFormat:@"%ld", (long)mode]]];
    } else {
        NSLog(@"Error: BlufiClient not connected or initialized. Cannot set device mode.");
        [self updateMessage:[self makeJsonWithCommand:@"set_device_mode_error" data:@"Client not ready"]];
    }
}

- (void)scanDeviceInfo {
    [self.espFBYBleHelper startScan:^(ESPPeripheral *_Nonnull device) {

        if (device.name == nil) return;

        if (self.filterContent != nil && ![self.filterContent isEqualToString:@""] &&
            ![device.name.lowercaseString containsString:self.filterContent.lowercaseString])
            return;

        self.dataDictionary[device.uuid.UUIDString] = device;
        [self updateMessage:[self makeScanDeviceJsonWithAddress:device.uuid.UUIDString name:device.name rssi:device.rssi]];
    }];
}

- (void)stopScan {
    [self.espFBYBleHelper stopScan];
    [self updateMessage:[self makeJsonWithCommand:@"stop_scan_ble" data:@"1"]];
}


- (void)connectPeripheral:(ESPPeripheral *)perripheral {
    self.connected = NO;
    self.device = perripheral;

    if (_blufiClient) {
        [_blufiClient close];
        _blufiClient = nil;
    }

    _blufiClient = [[BlufiClient alloc] init];
    _blufiClient.centralManagerDelete = self;
    _blufiClient.peripheralDelegate = self;
    _blufiClient.blufiDelegate = self;
    [_blufiClient connect:_device.uuid.UUIDString];
}

- (void)onDisconnected {
    if (_blufiClient) {
        [_blufiClient close];
    }
}

- (void)requestCloseConnection {
    if (_blufiClient) {
        [_blufiClient requestCloseConnection];
    }
}

- (void)requestDeviceWifiScan {
    if (_blufiClient) {
        [_blufiClient requestDeviceScan];
    }
}

- (void)negotiateSecurity {
    if (_blufiClient) {
        [_blufiClient negotiateSecurity];
    }
}

- (void)requestDeviceVersion {
    if (_blufiClient) {
        [_blufiClient requestDeviceVersion];
    }
}

- (void)configProvisionWithSSID:(NSString *)ssid password:(NSString *)password {
    BlufiConfigureParams *params = [[BlufiConfigureParams alloc] init];
    params.opMode = OpModeSta;
    params.staSsid = ssid;
    params.staPassword = password;

    if (_blufiClient && _connected) {
        [_blufiClient configure:params];
    }
}

// 在 EspBlufiPlugin.m 的 @implementation 块内添加以下方法

- (void)setApModelWithSSID:(NSString *)ssid password:(NSString *)password {
    // 检查 BlufiClient 是否已初始化并且已连接
    if (_blufiClient && _connected) {
        // 1. 创建 BlufiConfigureParams 实例
        BlufiConfigureParams *params = [[BlufiConfigureParams alloc] init];

        // 2. 设置操作模式为 SoftAP (假设 OpModeSoftAP 的值为 2，与 Android 对应)
        //    请根据 iOS 端 BlufiConfigureParams.h 中 OpMode 的定义确认具体值
        params.opMode = OpModeSoftAP; // 或者直接写 params.opMode = 2; 如果枚举值确认是 2

        // 3. 设置 SoftAP 的 SSID 和 Password
        params.softApSsid = ssid;
        params.softApPassword = password; // 注意：密码设置方法名需确认，可能是 softAPPAssword (如 Android) 或 softAPPassword

        // 4. 设置其他 SoftAP 参数 (使用 Android 代码中的默认值或根据需要调整)
        //    请确认 iOS 端 BlufiConfigureParams 是否有这些属性及正确的 setter 方法名
        params.softApChannel = 0;         // 默认频道
        params.softApMaxConnection = 1;   // 最大连接数
        // Security 设置需要根据 Blufi 协议和 iOS SDK 的具体实现来确定。
        // Android 中是 4 (可能代表 WPA2/WPA3)，iOS 可能是枚举或其他方式。
        // 这里假设有一个类似的属性和值，需要查阅 iOS SDK 文档或头文件确认。
        // 例如，如果枚举是 SecurityTypeWPA2_PSK = 4:
        // params.softAPSecurity = SecurityTypeWPA2_PSK;
        // 或者如果直接是整数值:
        params.softApSecurity = 4; // 需要确认具体值和属性名

        // 5. 调用 BlufiClient 的 configure 方法发送配置
        [_blufiClient configure:params];

        NSLog(@"iOS setApModel called with SSID: %@, Password: %@", ssid, password);
    } else {
        NSLog(@"Error: BlufiClient not connected or initialized. Cannot set AP mode.");
        // 可选：通过 updateMessage 发送错误信息给 Flutter
        // [self updateMessage:[self makeJsonWithCommand:@"set_ap_model_error" data:@"Client not ready"]];
    }
}

- (void)requestDeviceStatus {
    if (_blufiClient) {
        [_blufiClient requestDeviceStatus];
    }
}

- (void)postCustomData:(NSString *)data {

    if (_blufiClient && data != nil) {
        [_blufiClient postCustomData:[data dataUsingEncoding:NSUTF8StringEncoding]];
    }
}

- (NSMutableDictionary *)dataDictionary {
    if (!_peripheralDictionary) {
        _peripheralDictionary = [[NSMutableDictionary alloc] init];
    }
    return _peripheralDictionary;
}


- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    [self updateMessage:[self makeJsonWithCommand:@"peripheral_connect" data:@"1"]];
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    [self updateMessage:[self makeJsonWithCommand:@"peripheral_connect" data:@"0"]];
    self.connected = NO;
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    [self onDisconnected];
    [self updateMessage:[self makeJsonWithCommand:@"peripheral_disconnect" data:@"1"]];
    self.connected = NO;
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {

}

- (void)blufi:(BlufiClient *)client gattPrepared:(BlufiStatusCode)status service:(CBService *)service writeChar:(CBCharacteristic *)writeChar notifyChar:(CBCharacteristic *)notifyChar {
    if (status == StatusSuccess) {
        self.connected = YES;
        [self updateMessage:[self makeJsonWithCommand:@"blufi_connect_prepared" data:@"1"]];
        [self updateMessage:[self makeJsonWithCommand:@"GATT_SUCCESS" data:@"1"]];
    } else {
        [self onDisconnected];
        if (!service) {
            [self updateMessage:[self makeJsonWithCommand:@"blufi_connect_prepared" data:@"2"]];
        } else if (!writeChar) {
            [self updateMessage:[self makeJsonWithCommand:@"blufi_connect_prepared" data:@"3"]];
        } else if (!notifyChar) {
            [self updateMessage:[self makeJsonWithCommand:@"blufi_connect_prepared" data:@"4"]];
        }
    }
}

- (void)blufi:(BlufiClient *)client didNegotiateSecurity:(BlufiStatusCode)status {
    NSLog(@"Blufi didNegotiateSecurity %d", status);

    if (status == StatusSuccess) {
        [self updateMessage:[self makeJsonWithCommand:@"negotiate_security" data:@"1"]];
    } else {
        [self updateMessage:[self makeJsonWithCommand:@"negotiate_security" data:@"0"]];
    }
}

- (void)blufi:(BlufiClient *)client didReceiveDeviceVersionResponse:(BlufiVersionResponse *)response status:(BlufiStatusCode)status {

    if (status == StatusSuccess) {
        [self updateMessage:[self makeJsonWithCommand:@"device_version" data:response.getVersionString]];
    } else {
        [self updateMessage:[self makeJsonWithCommand:@"device_version" data:@"0"]];
    }
}

- (void)blufi:(BlufiClient *)client didPostConfigureParams:(BlufiStatusCode)status {
    if (status == StatusSuccess) {
        [self updateMessage:[self makeJsonWithCommand:@"configure_params" data:@"1"]];
    } else {
        [self updateMessage:[self makeJsonWithCommand:@"configure_params" data:@"0"]];
    }
}

- (void)blufi:(BlufiClient *)client didReceiveDeviceStatusResponse:(BlufiStatusResponse *)response status:(BlufiStatusCode)status {

    if (status == StatusSuccess) {
        [self updateMessage:[self makeJsonWithCommand:@"device_status" data:@"1"]];

        if ([response isStaConnectWiFi]) {
            [self updateMessage:[self makeWifiJsonWithCommand:@"device_wifi_connect" data:response]];
        } else {
            [self updateMessage:[self makeJsonWithCommand:@"device_wifi_connect" data:@"0"]];
        }
    } else {
        [self updateMessage:[self makeJsonWithCommand:@"device_status" data:@"0"]];
    }
}

- (void)blufi:(BlufiClient *)client didReceiveDeviceScanResponse:(NSArray

<BlufiScanResponse *> *)
scanResults status
:(BlufiStatusCode)status {

    if (status == StatusSuccess) {
//        NSMutableString *info = [[NSMutableString alloc] init];
//        [info appendString:@"Receive device scan results:\n"];
        for (BlufiScanResponse *response in scanResults) {
//            [info appendFormat:@"SSID: %@, RSSI: %d\n", response.ssid, response.rssi];
            [self updateMessage:[self makeWifiInfoJsonWithSsid:response.ssid rssi:response.rssi]];
        }
    } else {
        [self updateMessage:[self makeJsonWithCommand:@"wifi_info" data:@"0"]];
    }
}

- (void)blufi:(BlufiClient *)client didPostCustomData:(nonnull NSData

*)
data status
:(BlufiStatusCode)status {
    if (status == StatusSuccess) {
        [self updateMessage:[self makeJsonWithCommand:@"post_custom_data" data:@"1"]];
    } else {
        [self updateMessage:[self makeJsonWithCommand:@"post_custom_data" data:@"0"]];
    }
}

- (void)blufi:(BlufiClient *)client didReceiveCustomData:(NSData *)data status:(BlufiStatusCode)status {
    if (status == StatusSuccess) {
        NSString *customString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        customString = [customString stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
        [self updateMessage:[self makeJsonWithCommand:@"receive_device_custom_data" data:customString]];
    } else {
        [self updateMessage:[self makeJsonWithCommand:@"receive_device_custom_data" data:@"0"]];
    }

}

- (void)updateMessage:(NSString *)message {
    NSLog(@"%@", message);

    if (_stateStreamHandler.sink != nil) {
        self.stateStreamHandler.sink(message);
    }
}

- (NSString *)makeWifiJsonWithCommand:(NSString *)command data:(BlufiStatusResponse *)data {
    NSString *address = @"";
    if (self.device != nil) {
        address = self.device.uuid.UUIDString;
    }

    return [NSString stringWithFormat:@"{\"key\":\"%@\",\"value\":\"%s\",\"bssid\":\"%@\" ,\"ssid\":\"%@\" ,\"address\":\"%@\" ,\"name\":\"%@\"}", command, "1", data.staBssid, data.staSsid, address, _device.name];
}

- (NSString *)makeJsonWithCommand:(NSString *)command data:(NSString *)data {
    NSString *address = @"";
    if (self.device != nil) {
        address = self.device.uuid.UUIDString;
    }

    return [NSString stringWithFormat:@"{\"key\":\"%@\",\"value\":\"%@\",\"address\":\"%@\"}", command, data, address];
}

- (NSString *)makeScanDeviceJsonWithAddress:(NSString *)address name:(NSString *)name rssi:(int)rssi {
    return [NSString stringWithFormat:@"{\"key\":\"ble_scan_result\",\"value\":{\"address\":\"%@\",\"name\":\"%@\",\"rssi\":\"%d\"}}", address, name, rssi];
}

- (NSString *)makeWifiInfoJsonWithSsid:(NSString *)ssid rssi:(int)rssi {
    NSString *address = @"";
    if (self.device != nil) {
        address = self.device.uuid.UUIDString;
    }
    return [NSString stringWithFormat:@"{\"key\":\"wifi_info\",\"value\":{\"ssid\":\"%@\",\"rssi\":\"%d\",\"address\":\"%@\"}}", ssid, rssi, address];
}


- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
    if ([@"getPlatformVersion" isEqualToString:call.method]) {
        result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
    } else if ([@"scanDeviceInfo" isEqualToString:call.method]) {
        NSString *filter = call.arguments[@"filter"];
        if (filter != nil) {
            self.filterContent = filter;
        }
        [self scanDeviceInfo];
    } else if ([@"testFunction" isEqualToString:call.method]) {
        NSLog(@"testFunction is being executed from IOS native code.......");
    } else if ([@"stopScan" isEqualToString:call.method]) {
        [self stopScan];
    } else if ([@"connectPeripheral" isEqualToString:call.method]) {
        NSString *peripheral = call.arguments[@"peripheral"];
        [self connectPeripheral:self.peripheralDictionary[peripheral]];
    } else if ([@"setApModel" isEqualToString:call.method]) {
        NSString *ssid = call.arguments[@"ssid"];
        NSString *password = call.arguments[@"password"];
        if (ssid != nil) {
            [self setApModelWithSSID:ssid password:password ?: @""];
            result(nil);
        } else {
            result([FlutterError errorWithCode:@"INVALID_ARGUMENT" message:@"SSID is required for setApModel" details:nil]);
        }
    }
        // 新增 setDeviceMode 方法处理
    else if ([@"setDeviceMode" isEqualToString:call.method]) {
        NSNumber *modeNumber = call.arguments[@"mode"];
        if (modeNumber != nil) {
            NSInteger mode = [modeNumber integerValue];
            [self setDeviceMode:mode];
            result(@(YES)); // 返回成功
        } else {
            result([FlutterError errorWithCode:@"INVALID_ARGUMENT" message:@"mode is required for setDeviceMode" details:nil]);
        }
    }
    else if ([@"requestCloseConnection" isEqualToString:call.method]) {
        [self requestCloseConnection];
    } else if ([@"negotiateSecurity" isEqualToString:call.method]) {
        [self negotiateSecurity];
    } else if ([@"requestDeviceVersion" isEqualToString:call.method]) {
        [self requestDeviceVersion];
    } else if ([@"configProvision" isEqualToString:call.method]) {
        NSString *username = call.arguments[@"username"];
        NSString *password = call.arguments[@"password"];
        [self configProvisionWithSSID:username password:password];
    } else if ([@"requestDeviceStatus" isEqualToString:call.method]) {
        [self requestDeviceStatus];
    } else if ([@"requestDeviceWifiScan" isEqualToString:call.method]) {
        [self requestDeviceWifiScan];
    } else if ([@"sendCustomData" isEqualToString:call.method]) {
        NSString *customData = call.arguments[@"data"];
        [self postCustomData:customData];
    } else {
        result(FlutterMethodNotImplemented);
    }
}


@end

@implementation EspBlufiPluginStreamHandler

- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
    self.sink = eventSink;
    return nil;
}

- (FlutterError *)onCancelWithArguments:(id)arguments {
    self.sink = nil;
    return nil;
}

@end
